<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Enter the S-Parser</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Enter the S-Parser' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../inform7n.html">Inform7</a></li><li><a href="index.html">values</a></li><li><a href="index.html#4">Chapter 4: The S-Parser</a></li><li><b>Enter the S-Parser</b></li></ul></div>
<p class="purpose">The top-level nonterminals of the S-parser, which turns text into specifications.</p>

<ul class="toc"><li><a href="4-ets.html#SP1">&#167;1. Introduction</a></li><li><a href="4-ets.html#SP3">&#167;3. Top-level nonterminals</a></li><li><a href="4-ets.html#SP10">&#167;10. Void phrases</a></li><li><a href="4-ets.html#SP11">&#167;11. Actions</a></li></ul><hr class="tocbar">

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Introduction.</b>The purpose of the S-parser is to turn excerpts of text into specification
nodes. Nonterminals here almost all have names beginning with the "s-" prefix,
which indicates that their results are specifications. The simplest example is:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;s-plain-text&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    ==&gt; { -, </span><a href="2-spc.html#SP11" class="function-link"><span class="function-syntax">Specifications::new_UNKNOWN</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) };</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>And here is a curious variation, which is needed because equations are
parsed with completely different spacing rules, and don't respect word
boundaries. It matches any non-empty text where one of the words contains an
equals sign as one of its characters.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;s-plain-text-with-equals&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_THROUGH_WORDING</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">inchar32_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word_raw_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">]; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++)</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">] == </span><span class="character-syntax">'='</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">                ==&gt; { -, </span><a href="2-spc.html#SP11" class="function-link"><span class="function-syntax">Specifications::new_UNKNOWN</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">) };</span>
<span class="plain-syntax">                </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. Top-level nonterminals.</b>These five nonterminals are the most useful and powerful, so they're the
main junction between the S-parser and the rest of Inform.
</p>

<p class="commentary">These are coded as internals for efficiency's sake. We will often reparse the
same wording over and over, so we cache the results. But &lt;s-value&gt; matches
exactly the same text as &lt;s-value-uncached&gt;, and so on for the other four.
</p>

<p class="commentary">&lt;s-value&gt; looks for source text which can be evaluated &mdash; a constant, a
variable or other storage object, or a phrase to decide a value.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;s-value&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PreformCache::parse</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="function-syntax">&lt;s-value-uncached&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::is</span><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">, </span><span class="identifier-syntax">UNKNOWN_NT</span><span class="plain-syntax">)) { ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> }; }</span>
<span class="plain-syntax">    ==&gt; { -, </span><span class="identifier-syntax">spec</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>&lt;s-condition&gt; looks for a condition &mdash; anything legal after an
"if", in short. This includes sentence-like excerpts such as "six
animals have been in the Stables".
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;s-condition&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LocalVariables::make_necessary_callings</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PreformCache::parse</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">, </span><span class="function-syntax">&lt;s-condition-uncached&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::is</span><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">, </span><span class="identifier-syntax">UNKNOWN_NT</span><span class="plain-syntax">)) { ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> }; }</span>
<span class="plain-syntax">    ==&gt; { -, </span><span class="identifier-syntax">spec</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>&lt;s-non-action-condition&gt; is the same, but disallowing action patterns
as conditions, so for example "taking something" would not match.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;s-non-action-condition&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LocalVariables::make_necessary_callings</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">IF_MODULE</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">old_state</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ParseActionPatterns::enter_mode</span><span class="plain-syntax">(</span><span class="identifier-syntax">SUPPRESS_AP_PARSING</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PreformCache::parse</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">2</span><span class="plain-syntax">, </span><span class="function-syntax">&lt;s-condition-uncached&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">IF_MODULE</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">ParseActionPatterns::restore_mode</span><span class="plain-syntax">(</span><span class="identifier-syntax">old_state</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::is</span><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">, </span><span class="identifier-syntax">UNKNOWN_NT</span><span class="plain-syntax">)) { ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> }; }</span>
<span class="plain-syntax">    ==&gt; { -, </span><span class="identifier-syntax">spec</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b>&lt;s-type-expression&gt; is for where we expect to find the "type" of something
&mdash; for instance, the kind of value to be stored in a variable, or the
specification of a phrase argument.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;s-type-expression&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PreformCache::parse</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">3</span><span class="plain-syntax">, </span><span class="function-syntax">&lt;s-type-expression-uncached&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::is</span><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">, </span><span class="identifier-syntax">UNKNOWN_NT</span><span class="plain-syntax">)) { ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> }; }</span>
<span class="plain-syntax">    ==&gt; { -, </span><span class="identifier-syntax">spec</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. </b>&lt;s-descriptive-type-expression&gt; is the same thing, with one difference: it
allows nounless descriptions, such as "open opaque fixed in place", and to
this end it treats bare adjective names as descriptions rather than values. If
we have said "Colour is a kind of value. The colours are red, green and taupe.
A thing has a colour.", then "green" is parsed by &lt;s-descriptive-type-expression&gt;
as a description meaning "any thing which is green", but by &lt;s-type-expression&gt;
and &lt;s-value&gt; as a constant value of the kind "colour".
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;s-descriptive-type-expression&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax"> =</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">PreformCache::parse</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">4</span><span class="plain-syntax">, </span><span class="function-syntax">&lt;s-descriptive-type-expression-uncached&gt;</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Node::is</span><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">, </span><span class="identifier-syntax">UNKNOWN_NT</span><span class="plain-syntax">)) { ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> }; }</span>
<span class="plain-syntax">    ==&gt; { -, </span><span class="identifier-syntax">spec</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. </b>The following internal is just a shell for &lt;s-descriptive-type-expression&gt;,
but it temporarily changes the parsing mode to phrase token parsing, so that
kind variables will be read as formal prototypes.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;s-phrase-token-type&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">s</span><span class="plain-syntax"> = </span><span class="identifier-syntax">kind_parsing_mode</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">kind_parsing_mode</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PHRASE_TOKEN_KIND_PARSING</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax"> = </span><span class="function-syntax">&lt;s-descriptive-type-expression&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">kind_parsing_mode</span><span class="plain-syntax"> = </span><span class="identifier-syntax">s</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">t</span><span class="plain-syntax">) { ==&gt; { </span><span class="function-syntax">&lt;&lt;r&gt;&gt;</span><span class="plain-syntax">, </span><span class="function-syntax">&lt;&lt;rp&gt;&gt;</span><span class="plain-syntax"> }; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">    ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. </b>We will also define a convenient super-nonterminal which matches almost any
meaningful reference to data, so it's a convenient way of finding out whether
a new name will clash with some existing meaning.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;s-type-expression-or-value&gt;</span>
<span class="plain-syntax">    </span><span class="function-syntax">&lt;s-type-expression&gt;</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="function-syntax">&lt;s-value&gt;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. Void phrases.</b>The S-parser is also used by the main code compiler to turn phrases into
S-nodes, using &lt;s-command&gt; and &lt;s-say-command&gt;. These however need a
wrapper: instead of turning text into an S-node, we take text from an
existing node (in the structural parse tree for a routine), turn that
into a new S-node with an invocation list below it, then glue the list
back into the original tree but throw away the S-node head.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">SParser::parse_void_phrase</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><a href="4-ets.html#SP10" class="function-link"><span class="function-syntax">SParser::parse_phrase_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">SParser::parse_say_term</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><a href="4-ets.html#SP10" class="function-link"><span class="function-syntax">SParser::parse_phrase_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">SParser::parse_phrase_inner</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">as_say_term</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no node to parse"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::nonempty</span><span class="plain-syntax">(</span><span class="identifier-syntax">Node::get_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">results</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">as_say_term</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="function-syntax">&lt;s-command&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">Node::get_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)))) </span><span class="identifier-syntax">results</span><span class="plain-syntax"> = </span><span class="function-syntax">&lt;&lt;rp&gt;&gt;</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">as_say_term</span><span class="plain-syntax">) &amp;&amp; (</span><span class="function-syntax">&lt;s-say-command&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">Node::get_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">)))) </span><span class="identifier-syntax">results</span><span class="plain-syntax"> = </span><span class="function-syntax">&lt;&lt;rp&gt;&gt;</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">results</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">results</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax">)) </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax"> = </span><span class="identifier-syntax">results</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>&#167;11. Actions.</b>These are meaningful only for interactive fiction, and serve the "if" module:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;s-explicit-action&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">IF_MODULE</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">saved</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ParseActionPatterns::enter_mode</span><span class="plain-syntax">(</span><span class="identifier-syntax">PERMIT_TRYING_OMISSION</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;s-condition-uncached&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><span class="function-syntax">&lt;&lt;rp&gt;&gt;</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">ParseActionPatterns::restore_mode</span><span class="plain-syntax">(</span><span class="identifier-syntax">saved</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">S</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-rvl.html#SP22" class="function-link"><span class="function-syntax">Rvalues::is_CONSTANT_of_kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_stored_action</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            ==&gt; { -, </span><span class="identifier-syntax">S</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">AConditions::is_action_TEST_VALUE</span><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            ==&gt; { -, </span><span class="identifier-syntax">S</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">            ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">}</span>

<span class="function-syntax">&lt;s-constant-action&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">IF_MODULE</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">was</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ParseActionPatterns::enter_mode</span><span class="plain-syntax">(</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">FORBID_NONCONSTANT_ACTION_PARAMETERS</span><span class="plain-syntax"> + </span><span class="identifier-syntax">PERMIT_TRYING_OMISSION</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;s-condition-uncached&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><span class="function-syntax">&lt;&lt;rp&gt;&gt;</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">ParseActionPatterns::restore_mode</span><span class="plain-syntax">(</span><span class="identifier-syntax">was</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">S</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-rvl.html#SP22" class="function-link"><span class="function-syntax">Rvalues::is_CONSTANT_of_kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_stored_action</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            ==&gt; { -, </span><span class="identifier-syntax">S</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">AConditions::is_action_TEST_VALUE</span><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            ==&gt; { -, </span><span class="identifier-syntax">S</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">            ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="3-ll.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-vm.html">1</a></li><li class="progresschapter"><a href="2-spc.html">2</a></li><li class="progresschapter"><a href="3-pl.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresscurrent">ets</li><li class="progresssection"><a href="4-cad.html">cad</a></li><li class="progresssection"><a href="4-teav.html">teav</a></li><li class="progresssection"><a href="4-varc.html">varc</a></li><li class="progresssection"><a href="4-cap.html">cap</a></li><li class="progresssection"><a href="4-il.html">il</a></li><li class="progresssection"><a href="4-inv.html">inv</a></li><li class="progresssection"><a href="4-pi.html">pi</a></li><li class="progresschapter"><a href="5-dsh.html">5</a></li><li class="progressnext"><a href="4-cad.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

